package com.Tielen.app.matcher.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.Teilen.app.db.main.DBWrapper;
import com.Telien.app.request.object.DriverRequest;
import com.Telien.app.request.object.rideService;

import de.micromata.opengis.kml.v_2_2_0.Coordinate;

public class MatcherService{
	private ArrayList<DriverRequest> driverRequests = null;
	private DriverRequest bestMatchRequest = null;
	
	public MatcherService(){
		DBWrapper db = new DBWrapper();
		/*
		 * in the future we should modify this retrieval from DB and ensure seats open, order by point, etc 
		 */
		driverRequests = db.getAllDriverRequests();
	}
	
	/*
	 * returns distance in miles
	 * assumes 'crow-fly' distance
	 */
	public double distance(double lat1, double lon1, double lat2, double lon2) {
	  double theta = lon1 - lon2;
	  double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
	  dist = Math.acos(dist);
	  dist = rad2deg(dist);
	  dist = dist * 60 * 1.1515;

	  return (dist);
	}
	
	public double distance(Coordinate x, Coordinate y){
		return distance(x.getLatitude(), x.getLongitude(), y.getLatitude(), y.getLongitude());
	}
	
	public double deg2rad(double deg) {
	  return (deg * Math.PI / 180.0);
	}
	
	public double rad2deg(double rad) {
	  return (rad * 180 / Math.PI);
	}
	
	public boolean findMatch(DriverRequest dr){
		double closestDistance = 201.0;
		Calendar cal = Calendar.getInstance();
		cal.setTime(dr.getStartTime());
		
		for(DriverRequest dr2 : driverRequests){
			Calendar cal2 = Calendar.getInstance();
			cal2.setTime(dr2.getStartTime());
			double timeDif = cal.getTimeInMillis() - cal2.getTimeInMillis();
			if(Math.abs(timeDif) > 30 * 60 * 1000){
				continue;
			}
			
			double startDist = distance(dr.getStartCord(), dr2.getStartCord());
			double endDist = distance(dr.getEndCord(), dr2.getEndCord());
			//our start and end have to be close enough
			//in the future, we should probably not check already matched or if we do consider seat availability
			if(startDist <= dr.getStartMileRadius() && startDist <= dr2.getStartMileRadius() &&
					endDist <= dr.getEndMileRadius() && endDist <= dr2.getEndMileRadius() &&
					startDist + endDist < closestDistance ){
				bestMatchRequest = dr2;
				closestDistance = startDist + endDist;
			}
		}
		if(bestMatchRequest == null){
			return false;
		}
		else{
			return true;
		}
	}
	
	public void createRideRequest(DriverRequest dr) throws Exception{
		if(bestMatchRequest == null){
			System.out.println("**I pitty the fool who doesn't initialize the bestMatchRequest**");
			throw new Exception("bestMatchRequest must be initialized before calling MatcherService.createRideRequest");
		}
		
		DBWrapper db = new DBWrapper();
		List<rideService> rides = db.getSessions();
		int rideSessionId = db.selectSessionsSize();
		// I'm replacing how you get a new sessionID - Brian
		/*int lastRideSessionID = 1;
		if(rides != null && !rides.isEmpty()){
			lastRideSessionID = rides.get(rides.size() -1).getrideSessionID();
		}*/
		//rideService ride = new rideService(rideSessionId,Integer.parseInt(dr.getUserUUID()), Integer.parseInt(bestMatchRequest.getUserUUID()), dr.getStartTime(), false);
		//db.createSession(ride);
	}
}